/**
 * created by dt at 2025/5/4
 * 
 */

import { World } from "./World";

/**
 * Service基类
 * 服务是单例的，用于管理全局状态和功能
 */
export abstract class Service {
    protected world: World;

    constructor(world: World, ...args: any[]) {
        this.world = world;
    }

    // 服务初始化
    abstract onStart(): void;

    // // 服务销毁
    // abstract onDestroy(): void;

    get typeName() {
        return Service.getTypeName(this.constructor);
    }

    static getTypeName(type: any) {
        return type["ClassName"];
    }
}

export class ServiceRegistry {
    private static _registry = new Map<string, any>();

    static register(typeName: string, constructor: any) {
        if (this._registry.has(typeName)) {
            throw new Error(`Service ${typeName} already registered`);
        }

        constructor["ClassName"] = typeName;
        this._registry.set(typeName, constructor);

        // 日志
        console.log(`Service ${typeName} registered`);
    }

    static getByTypeName(typeName: string) {
        return this._registry.get(typeName);
    }
}

// 通过一个decorator来注册服务
export function ecs_service(name: string) {
    return function (target: any) {
        ServiceRegistry.register(name, target);
    }
}

export class ServiceManager {
    private _world: World;
    private _services: Map<string, Service> = new Map();

    constructor(world: World) {
        this._world = world;
    }

    start() {
        this._services.forEach((service) => {
            service.onStart();
        });
    }

    addService<T extends Service>(serviceType: new (world: World, ...args: any[]) => T, ...args: any[]): T {
        const typeName = Service.getTypeName(serviceType);
        if (this._services.has(typeName)) {
            throw new Error(`Service ${typeName} already exists`);
        }

        const service = new serviceType(this._world, ...args);
        this._services.set(typeName, service);
        
        return service;
    }

    getService<T extends Service>(serviceType: { prototype: T }): T {
        const typeName = Service.getTypeName(serviceType);
        const service = this._services.get(typeName);
        if (!service) {
            throw new Error(`Service ${typeName} not found`);
        }
        return service as T;
    }

    tryGetService<T extends Service>(serviceType: { prototype: T }): T | undefined {
        const typeName = Service.getTypeName(serviceType);
        return this._services.get(typeName) as T;
    }
} 